import { Injectable } from '@angular/core';
import { Http, Response, URLSearchParams } from '@angular/http';
import { Headers, RequestOptions ,RequestMethod,RequestOptionsArgs} from '@angular/http';
import 'rxjs/add/operator/toPromise';
import 'rxjs/add/operator/timeout';
import { StorageService } from "./StorageService";
import { UserVo } from "./../model/UserVo";
import { SERVER_URL,IS_DEBUG,REQUEST_TIMEOUT } from './Config';
import {NativeService} from "./NativeService";
import {Observable, TimeoutError} from "rxjs";
import {Utils} from "./Utils";
import {GlobalData} from "./GlobalData";
import {Logger} from "./Logger";

import { Component, Injector, } from '@angular/core';
import { Loading, LoadingController, ToastController } from 'ionic-angular';
@Injectable()
export class HttpService {
  myInfoLocal: any;
  local: Storage;
  loader: Loading;
  timeOut = 5000;//请求5秒
  get loadingCtrl(): LoadingController { return this.injector.get(LoadingController); };
  get toastCtrl(): ToastController { return this.injector.get(ToastController); };

  isBusy = false;
  constructor(
    private http: Http,
    public injector: Injector,
    private storageService: StorageService,
    public logger: Logger,
    public globalData: GlobalData,
    public nativeService: NativeService
    ) {

    //this.local = new Storage(LocalStorage);
  }



  //是滚动页，不产生加载进度条
  isScrollPage(param) {
    1
    if (param) //有参数
    {
      if (param.hasOwnProperty('pageNo')) {  //有 > 1 的页码 ，表示页尾往上拉，不需要提示
        //   alert('有页码')
        return false;
      }

    }

    return true;
  }

  /**
   * 显示加载进度条
   */
  showLoading = (content: string = "Please wait...") => {
    this.loader = this.loadingCtrl.create({
      content: content,
      duration: 0
    });
    this.isBusy = true;
    this.loader.present();
  }

  /**
   * 关闭加载进度条
   */
  closeLoading = () => {
    this.isBusy = false;
   // this.loader.dismiss();
    if (this.loader) {
      this.loader.dismiss();
      this.loader = null
    }
  }

  //显示出错信息
  presentToast = (errMsg) => {
    let toast = this.toastCtrl.create({
      message: errMsg,
      duration: 4000,
      position: 'bottom'
    });

    toast.onDidDismiss(() => {
      console.log('Dismissed toast');
    });

    toast.present();
  }


  //get 请求
  public httpGetWithAuth(url: string, body: any = null) {
    if (url.indexOf('http') == -1)
      url = SERVER_URL + url;
    //this.showLoading();
    let user = this.storageService.read<UserVo>('UserInfo');
    var headers = new Headers();
    headers.append('Content-Type', 'application/json');
    headers.append('Authorization', user.admin_id + '-' + user.UserToken);
    let options = new RequestOptions({ headers: headers });
    if (body) {
      let params: URLSearchParams = new URLSearchParams();

      for (let subName in body) {
        let subValue = body[subName];
        params.set(subName, subValue);
      }
      options.search = params;
    }

    return this.http.get(url, options).timeout(this.timeOut).toPromise()
      .then(
      res => JSON.parse(res["_body"].toString())

      )
      .catch(err => {
        this.handleError(err);
      });
  }


  public httpGetNoAuth(url: string, body: any = null) {

    if (url.indexOf('http') == -1)
      url = SERVER_URL + url;
     //this.showLoading();
    var headers = new Headers();
    headers.append('Content-Type', 'application/json');
    let options = new RequestOptions({ headers: headers });
    if (body) {
      let params: URLSearchParams = new URLSearchParams();
      for (let subName in body) {
        let subValue = body[subName];
        params.set(subName, subValue);
      }
      options.search = params;
    }
    return this.http.get(url, options).timeout(this.timeOut).toPromise()
      .then(
      res => {
       //  this.closeLoading();
        // console.log(res);
        return JSON.parse(res["_body"].toString());

      })
      .catch(err => {
        this.handleError(err);
      });
  }

  public httpPostNoAuth(url: string, body: any) {
    if (url.indexOf('http') == -1)
      url = SERVER_URL + url;
    //this.showLoading();
    
    var headers = new Headers();
    headers.append('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8');
    let options = new RequestOptions({ headers: headers });
    let urlparam: URLSearchParams = this.objToSearchParams(body);
    return this.http.post(url, urlparam, options).timeout(this.timeOut).toPromise()
      .then(
      res => {
        this.closeLoading();
        return JSON.parse(res["_body"].toString());
      })
      .catch(err => {
        this.handleError(err);
      }); 
  }

  public httpPostWithAuth(url: string, body: any) {
    if (url.indexOf('http') == -1)
      url = SERVER_URL + url;
    //this.showLoading();
    let user = this.storageService.read<UserVo>('UserInfo');
    var headers = new Headers();
    headers.append('Content-Type', 'application/json');
    headers.append('Authorization', user.admin_id + '-' + user.UserToken);
    let options = new RequestOptions({ headers: headers });
    return this.http.post(url, body, options).toPromise()
      .then(
      res => {
        //this.closeLoading();
        return JSON.parse(res["_body"].toString());
        // else {
        //     var err = new Error("后台返回数据格式错误");
        //     throw err;
        // }
      })
      .catch(err => {
        this.handleError(err);
      });
  }


  // private handleError(error: Response | any) {
  //     alert("后台出错\n" + JSON.stringify(error));

  // }

  private handleError = (error: Response | any) => {
    if (this.isBusy == false)
      this.closeLoading();


    let msg = '请求失败';
    if (error.status == 0) {
      msg = '无法访问设定的服务器地址';
    }
    if (error.status == 400) {
      msg = '请求无效';
      console.log('请检查参数类型是否匹配');
    }
    if (error.status == 404) {
      msg = '请求资源不存在';
      console.error(msg + '，请检查路径是否正确');
    }
    console.log(error);
    //alert(msg);//这里使用ToastController

    this.presentToast(msg);
    return { success: false, msg: msg };
  }

  /**
   * @param obj　参数对象
   * @return {string}　参数字符串
   * @example
   *  声明: var obj= {'name':'小军',age:23};
   *  调用: toQueryString(obj);
   *  返回: "?name=%E5%B0%8F%E5%86%9B&age=23"
   */
  private toQueryString(obj) {
    let ret = [];
    for (let key in obj) {
      key = encodeURIComponent(key);
      let values = obj[key];
      if (values && values.constructor == Array) {//数组
        let queryValues = [];
        for (let i = 0, len = values.length, value; i < len; i++) {
          value = values[i];
          queryValues.push(this.toQueryPair(key, value));
        }
        ret = ret.concat(queryValues);
      } else { //字符串
        ret.push(this.toQueryPair(key, values));
      }
    }
    return '?' + ret.join('&');
  }

  /**
   *
   * @param obj
   * @return {string}
   *  声明: var obj= {'name':'小军',age:23};
   *  调用: toQueryString(obj);
   *  返回: "name=%E5%B0%8F%E5%86%9B&age=23"
   */
  private toBodyString(obj) {
    let ret = [];
    for (let key in obj) {
      key = encodeURIComponent(key);
      let values = obj[key];
      if (values && values.constructor == Array) {//数组
        let queryValues = [];
        for (let i = 0, len = values.length, value; i < len; i++) {
          value = values[i];
          queryValues.push(this.toQueryPair(key, value));
        }
        ret = ret.concat(queryValues);
      } else { //字符串
        ret.push(this.toQueryPair(key, values));
      }
    }
    return ret.join('&');
  }

  private toQueryPair(key, value) {
    if (typeof value == 'undefined') {
      return key;
    }
    return key + '=' + encodeURIComponent(value === null ? '' : String(value));
  }



  public post(url: string, body: any = {}): Observable<any> {
    return this.request(url, new RequestOptions({
      method: RequestMethod.Post,
      body: body,
      headers: new Headers({
        'Content-Type': 'application/json; charset=UTF-8'
      })
    }));
  }


  /** 参数对象 转 urlparam */
  objToSearchParams(obj): URLSearchParams {
    let params: URLSearchParams = new URLSearchParams();
    for (var key in obj) {
      if (obj.hasOwnProperty(key))
        params.set(key, obj[key]);
    }
    return params;
  }

    /**
   * 格式化url使用默认API地址:SERVER_URL
   */
  private formatUrlDefaultApi(url: string = ''): string {
    return Utils.formatUrl(url.startsWith('http') ? url : SERVER_URL + url)
  }


  public request(url: string, options: RequestOptionsArgs): Observable<Response> {
    url = this.formatUrlDefaultApi(url);
    if (url.indexOf(SERVER_URL) != -1) {
      options = this.addAuthorizationHeader(options);
    }
    IS_DEBUG && console.log('%c 请求前 %c', 'color:blue', '', 'url', url, 'options', options);
    this.nativeService.showLoading();
    return Observable.create(observer => {
      this.http.request(url, options).timeout(REQUEST_TIMEOUT).subscribe(res => {
        let result = this.requestSuccessHandle(url, options, res);
        result.success ? observer.next(result.data) : observer.error(result.data);
      }, err => {
        observer.error(this.requestFailedHandle(url, options, err));
      });
    });
  }



  /**
   * 处理请求成功事件
   */
  requestSuccessHandle(url: string, options: RequestOptionsArgs, res: Response) {
    this.nativeService.hideLoading();
    let json = res.json();
    if (url.indexOf(SERVER_URL) != -1) {
      if (json.code != 1) {
        IS_DEBUG && console.log('%c 请求失败 %c', 'color:red', '', 'url', url, 'options', options, 'err', res);
        this.nativeService.alert(json.msg || '请求失败,请稍后再试!');
        return {success: false, data: json.data};
      } else {
        IS_DEBUG && console.log('%c 请求成功 %c', 'color:green', '', 'url', url, 'options', options, 'res', res);
        return {success: true, data: json.data};
      }
    } else {
      return {success: true, data: json};
    }
  }



  /**
   * 处理请求失败事件
   */
  private requestFailedHandle(url: string, options: RequestOptionsArgs, err: Response) {
    IS_DEBUG && console.log('%c 请求失败 %c', 'color:red', '', 'url', url, 'options', options, 'err', err);
    this.nativeService.hideLoading();
    if (err instanceof TimeoutError) {
      this.nativeService.alert('请求超时,请稍后再试!');
    } else if (!this.nativeService.isConnecting()) {
      this.nativeService.alert('请连接网络');
    } else {
      let status = err.status;
      let msg = '请求发生异常';
      if (status === 0) {
        msg = '请求失败，请求响应出错';
      } else if (status === 404) {
        msg = '请求失败，未找到请求地址';
      } else if (status === 500) {
        msg = '请求失败，服务器出错，请稍后再试';
      }
      this.nativeService.alert(msg);
      this.logger.httpLog(err, msg, {
        url: url,
        status: status
      });
    }
    return err;
  }



  public get(url: string, paramMap: any = null): Observable<any> {
    return this.request(url, new RequestOptions({
      method: RequestMethod.Get,
      search: HttpService.buildURLSearchParams(paramMap)
    }));
  }



  /**
   * 给请求头添加权限认证token
   */
  private addAuthorizationHeader(options: RequestOptionsArgs): RequestOptionsArgs {
    let token = this.globalData.token;
    if (options.headers) {
      options.headers.append('Authorization', 'Bearer ' + token);
    } else {
      options.headers = new Headers({
        'Authorization': 'Bearer ' + token
      });
    }
    return options;
  }

  /**
   * 将对象转为查询参数
   */
  private static buildURLSearchParams(paramMap): URLSearchParams {
    let params = new URLSearchParams();
    if (!paramMap) {
      return params;
    }
    for (let key in paramMap) {
      let val = paramMap[key];
      if (val instanceof Date) {
        val = Utils.dateFormat(val, 'yyyy-MM-dd hh:mm:ss')
      }
      params.set(key, val);
    }
    return params;
  }


}